package com.zy.web.controller.business;

import com.alibaba.fastjson2.JSONObject;
import com.zy.business.domain.TbAttendanceRecord;
import com.zy.business.domain.TbPunchCard;
import com.zy.business.domain.TbReissueCard;
import com.zy.business.domain.TbShift;
import com.zy.business.mapper.AttendanceMapper;
import com.zy.business.mapper.PunchCardMapper;
import com.zy.business.mapper.ReissueCardMapper;
import com.zy.business.service.PunchCardService;
import com.zy.business.service.ReissueCardService;
import com.zy.business.service.ShiftService;
import com.zy.common.annotation.Log;
import com.zy.common.annotation.RepeatSubmit;
import com.zy.common.config.RuoYiConfig;
import com.zy.common.constant.CacheConstants;
import com.zy.common.core.controller.BaseController;
import com.zy.common.core.domain.AjaxResult;
import com.zy.common.core.domain.entity.SysUser;
import com.zy.common.core.page.TableDataInfo;
import com.zy.common.core.redis.RedisCache;
import com.zy.common.enums.BusinessType;
import com.zy.common.utils.DateUtils;
import com.zy.common.utils.SecurityUtils;
import com.zy.common.utils.StringUtils;
import com.zy.common.utils.WebUtil;
import com.zy.common.utils.file.FileUploadUtils;
import com.zy.system.mapper.SysUserMapper;
import com.zy.system.service.ISysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@Api(tags = "考勤打卡接口")
@RequestMapping("/punchCard")
public class PunchCardController extends BaseController {

    @Autowired
    private PunchCardService punchCardService;

    @Resource
    private SysUserMapper userMapper;

    @Resource
    private PunchCardMapper punchCardMapper;

    @Resource
    private AttendanceMapper attendanceMapper;

    @Autowired
    private ISysUserService userService;

    @Resource
    private ReissueCardMapper reissueCardMapper;

    @Autowired
    private RedisCache redisCache;

    @Value("${APPID}")
    private String APPID;

    @Value("${APPSECRET}")
    private String APPSECRET;

    @Autowired
    private ReissueCardService reissueCardService;

    @Autowired
    private ShiftService tbShiftService;

    @GetMapping("/list")
    @ApiOperation(value = "获取员工的当月出勤率")
    public AjaxResult list() {
        List<TbPunchCard> punchCards = punchCardService.getList();
        return AjaxResult.success(punchCards);
    }

    @GetMapping("/getListByDate")
    @ApiOperation(value = "获取当天所有数据")
    public AjaxResult getListByDate() {
        List<Map<String, Object>> punchCards = punchCardService.getListByDateRemind();
        return AjaxResult.success(punchCards);
    }


    @GetMapping("/getPunchCardListByUserId")
    @ApiOperation(value = "根据userId获取用户考勤列表")
    public AjaxResult getPunchCardListByUserId(@RequestParam(name="userId") Long userId, String date) {
        List<Map<String, Object>> punchCards = punchCardService.getListByDate(userId,date);
        return AjaxResult.success(punchCards);
    }

    @GetMapping("/getCurrentRecord")
    @ApiOperation(value = "获取当月考勤记录")
    public AjaxResult getCurrentRecord(@RequestParam(name="userId") Long userId){
        Map<String, Object> recordMap = punchCardService.getCurrentRecord(userId);
        return AjaxResult.success(recordMap);
    }

    @ApiOperation(value = "获取用户信息")
    @GetMapping("/getUserInfo")
    public AjaxResult getUserInfo(@RequestParam(name="code") String code, String phone){
        String openUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+APPID+"&secret="+APPSECRET+"&code="+code+"&grant_type=authorization_code";
        JSONObject result = WebUtil.doGet(openUrl);
        String accessToken = null;
        String openId = null;
        if (null != result) {
            accessToken = result.getString("access_token");
            openId = result.getString("openid");
        }
        String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token="+accessToken+"&openid="+openId+"&lang=zh_CN";
        JSONObject resultUser = WebUtil.doGet(userInfoUrl);
        if (null != resultUser) {
            String openid = resultUser.getString("openid");
            SysUser user = userMapper.getUserByOpenId(openid);
            if(user!=null){
                return AjaxResult.success(user);
            }
        }
        return AjaxResult.success(resultUser);
    }


    public String getAccessToken(){
        String accessToken = redisCache.getCacheObject(CacheConstants.ACCESS_TOKEN_KEY);
        if(StringUtils.isEmpty(accessToken)){
            String openUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+APPID+"&secret="+APPSECRET;
            JSONObject result = WebUtil.doGet(openUrl);
            accessToken = result.getString("access_token");
            Integer expiresIn = result.getInteger("expires_in");
            redisCache.setCacheObject(CacheConstants.ACCESS_TOKEN_KEY, accessToken, expiresIn, TimeUnit.SECONDS);
        }
        return accessToken;
    }

    public String downImage(String mediaId) throws IOException {
        String basePath = RuoYiConfig.getUploadPath();
        String filePath = "";
        String fileName = "";
        String accessToken = getAccessToken();
        String requestUrl = " https://api.weixin.qq.com/cgi-bin/media/get?access_token="+accessToken+"&media_id="+mediaId;
        try {
            URL url = new URL(requestUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoInput(true);
            conn.setRequestMethod("GET");
            // 将mediaId作为文件名
            fileName = StringUtils.format("{}/{}.{}", DateUtils.datePath(),mediaId,"jpg");
            filePath = basePath + File.separator + fileName;
            BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
            File file = new File(filePath);
            if (!file.exists())
            {
                if (!file.getParentFile().exists())
                {
                    file.getParentFile().mkdirs();
                }
            }
            FileOutputStream fos = new FileOutputStream(file);
            byte[] buf = new byte[8096];
            int size = 0;
            while ((size = bis.read(buf)) != -1)
                fos.write(buf, 0, size);
            fos.close();
            bis.close();
            conn.disconnect();
            String info = String.format("下载媒体文件成功，filePath=" + filePath);
            System.out.println(info);
        } catch (Exception e) {
            String error = String.format("下载媒体文件失败：%s", e);
            System.out.println(error);
        }
        return FileUploadUtils.getPathFileName(basePath,fileName);
    }



    @ApiOperation(value = "获取用户信息")
    @GetMapping("/getUserInfoByOpenId")
    public AjaxResult getUserInfoByOpenId(@RequestParam(name="openId") String openId, String phone){
        SysUser user = userMapper.getUserByPhone(phone);
        if(user!=null){
            if(StringUtils.isNotEmpty(user.getOpenId())&&!user.getOpenId().equals(openId)){
                return AjaxResult.error(-1,"此微信账号已绑定其他用户,请联系管理员！");
            }
            user.setOpenId(openId);
            user.setUpdateBy(userService.selectUserById(1L).getUserName());
            user.setUpdateTime(new Date());
            userMapper.updateUser(user);
        }else{
            return AjaxResult.error(-1,"系统无此用户,请联系管理员！");
        }
        return AjaxResult.success(user);
    }

    @PostMapping("/clockIn")
    @ApiOperation(value = "用户打卡")
    public AjaxResult clockIn(@RequestBody TbAttendanceRecord record) {
        try {
            if(StringUtils.isNotEmpty(record.getOpenId())){
                SysUser user =  userMapper.getUserByOpenId(record.getOpenId());
                if(null != user){
                    record.setUserId(Long.valueOf(user.getDingUserId()));
                    record.setUserCheckTime(new Date());
                    record.setWorkDate(new Date());
                    if(StringUtils.isNotEmpty(record.getPhoneUrl())){
                        String phoneUrl = downImage(record.getPhoneUrl());
                        record.setPhoneUrl(phoneUrl);
                    }
                    attendanceMapper.insert(record);
                    TbPunchCard punchCard = punchCardService.getLastPunchCard(user.getDingUserId());
                    if(punchCard.getStatus()==0){
                        punchCard.setStatus(4);
                        punchCard.setPunchCardTime(new Date());
                        punchCard.setPunchCardType(record.getSourceType());
                        punchCard.setAddress(record.getAddress());
                        punchCard.setAttendanceId(record.getId());
                        punchCardService.sendSuccessMessage(punchCard);
                    }else if(punchCard.getStatus()==2){
                        if (punchCard.getPunchCardTime()==null){
                            punchCard.setAttendanceId(record.getId());
                            punchCard.setPunchCardTime(new Date());
                            punchCardService.sendSuccessMessage(punchCard);
                        }
                    }
                    punchCard.setUpdateTime(new Date());
                    punchCardService.updateById(punchCard);
                    return AjaxResult.success("打卡成功！");
                }else{
                    return AjaxResult.error(506,"系统无此用户，请联系管理员！");
                }
            }
            return AjaxResult.error(500,"openId为空！");
        } catch (Exception e){
            e.printStackTrace();
            return AjaxResult.error(e.getMessage());
        }
    }

    @ApiOperation("获取票据")
    @GetMapping("/getJsTicket")
    public AjaxResult getWeJsTicket(String url) {
        Map<String, Object> data= new HashMap<>();
        try {
            // 获取微信signature
            WxJsapiSignature sin = getJsapiSignture(url);
            data.put("appId", sin.getAppId());
            data.put("timestamp", sin.getTimestamp());
            data.put("nonceStr", sin.getNonceStr());
            data.put("signature", sin.getSignature());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.success(data);
    }

    public WxJsapiSignature getJsapiSignture(String url) throws WxErrorException {
        System.out.println(getAccessToken()+"-------------------------------");
        // 替换成自己的appId和secret
        WxMpService wxMpService = new WxMpServiceImpl();

        WxMpInMemoryConfigStorage config = new WxMpInMemoryConfigStorage();
        config.setAppId(APPID);
        config.setSecret(APPSECRET);

        wxMpService.setWxMpConfigStorage(config);
        WxJsapiSignature wxJsapiSignature = wxMpService.createJsapiSignature(url);
        //wxJsapiSignature中可以直接获取签名信息 且方法内部添加了缓存功能
        redisCache.setCacheObject(CacheConstants.ACCESS_TOKEN_KEY, config.getAccessToken(), (int)(config.getExpiresTime()-System.currentTimeMillis()), TimeUnit.MILLISECONDS);
        System.out.println(getAccessToken()+"++++++++++++++++++++++++++++++++");
        return wxJsapiSignature;
    }

    @GetMapping(value="/getList")
    @ApiOperation(value = "获取打卡列表数据")
    public AjaxResult getList(Long dingUserId, String date){
        if (StringUtils.isEmpty(date)){
            SimpleDateFormat formatTemp = new SimpleDateFormat("yyyy-MM-dd");
            date = formatTemp.format(new Date());
        }
        List<TbAttendanceRecord> list = attendanceMapper.getListByWorkDateList(dingUserId,date);
        return AjaxResult.success(list);
    }

    @GetMapping("/getUserMonthData")
    @ApiOperation(value = "我的考勤--日历数据")
    public AjaxResult getUserMonthData(@RequestParam(name="month") String month,Long userId){
        List<Map<String,Object>> dataList = punchCardService.getUserMonthData(month,userId);
        return AjaxResult.success(dataList);
    }

    @GetMapping("/getUserDataByDate")
    @ApiOperation(value = "获取用户某一天的考勤数据")
    public AjaxResult getUserDataByDate( @RequestParam(name="date") String date,Long userId){
        if (userId==null){
            userId = SecurityUtils.getUserId();
        }
        Map<String,Object> dataMap = new HashMap<>();
        List<Map<String, Object>> punchCardList = punchCardMapper.selectMyAttendance(userId,date);
        dataMap.put("punchCardList",punchCardList);
        TbShift shift = tbShiftService.selectTbShiftById();
        dataMap.put("shift",shift);
        return AjaxResult.success(dataMap);
    }

    @GetMapping(value="/getDeptAttendance")
    @ApiOperation(value = "获取成员考勤数据")
    public TableDataInfo getDeptAttendance(@RequestParam String month, String name){
        return punchCardService.getDeptAttendance(month, name);
    }

    @PostMapping("/reissueCard")
    @ApiOperation(value = "补卡申请")
    @RepeatSubmit
    public AjaxResult reissueCard(@RequestBody TbReissueCard reissueCard){
        return reissueCardService.saveReissueCard(reissueCard);
    }

    @GetMapping("/reissueList")
    @ApiOperation(value = "获取补卡列表(type:1我的补卡申请2补卡审核)")
    public TableDataInfo reissueList(@RequestParam Integer type, Integer status){
        startPage();
        List<TbReissueCard> reissueCardList = reissueCardService.getReissueCardList(type,status);
        return getDataTable(reissueCardList);
    }

    @PostMapping("/auditReissue")
    @Log(title = "审核补卡", businessType = BusinessType.AUDIT)
    @ApiOperation(value = "审核补卡")
    @RepeatSubmit
    public AjaxResult auditReissue(@RequestBody TbReissueCard reissueCard ){
        return reissueCardService.auditReissue(reissueCard);
    }

    @GetMapping("/getReissue")
    @ApiOperation(value = "获取补卡详情")
    public AjaxResult getReissue(@RequestParam Long reissueId){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        TbReissueCard reissueCard = reissueCardMapper.selectById(reissueId);
        reissueCard.setUserName(userMapper.selectUserById(reissueCard.getUserId()).getName());
        TbShift shift = tbShiftService.selectTbShiftById();
        if (reissueCard!=null){
            TbPunchCard punchCard = punchCardService.getById(reissueCard.getPunchCardId());
            String reissueCardDate = sdf.format(punchCard.getCreateTime())+" ";
            if (punchCard.getState()==1){
                reissueCardDate += shift.getStartTime1();
            }
            if (punchCard.getState()==2){
                reissueCardDate += shift.getEndTime1();
            }
            if (punchCard.getState()==3){
                reissueCardDate += shift.getStartTime2();
            }
            if (punchCard.getState()==4){
                reissueCardDate += shift.getEndTime2();
            }
            reissueCard.setReissueCardDate(reissueCardDate);
        }
        return AjaxResult.success(reissueCard);
    }

    @ApiOperation(value = "报表导出")
    @GetMapping("/exportReport")
    public void exportReport(HttpServletResponse response, String beginDate, String endDate){
        punchCardService.exportReport(beginDate,endDate,response);
    }

    @ApiOperation(value = "打卡记录导出")
    @GetMapping("/exportPunchCard")
    public void exportPunchCard(HttpServletResponse response, String beginDate, String endDate){
        punchCardService.exportPunchCard(beginDate,endDate,response);
    }

}
